package org.road0329.dlt698.axdr;

import org.road0329.dlt698.ReverseByteArrayInputStream;
import org.road0329.dlt698.ReverseByteArrayOutputStream;
import org.road0329.dlt698.asn1.axdr.AxdrEnum;
import org.road0329.dlt698.asn1.axdr.AxdrNull;
import org.road0329.dlt698.asn1.axdr.AxdrSequenceOf;
import org.road0329.dlt698.asn1.axdr.AxdrType;

import java.io.IOException;

public class MS extends AxdrType {
    private byte[] dataCode = null;
    private Choice choice = Choice._ERR_NONE_SELECTED;
    private AxdrNull nom = null;
    private AxdrNull allmaddr = null;
    private SubSeqOfUnsigned8 groupmtype = null;
    private SubSeqOfTsa groupmaddr = null;
    private SubSeqOfUnsigned16 groupsetindex = null;
    private SubSeqOfRegion regiontype = null;
    private SubSeqOfRegion regionaddr = null;
    private SubSeqOfRegion regionsetindex = null;

    public MS() {
    }

    public byte[] getDataCode() {
        return dataCode;
    }

    public Choice getChoice() {
        return choice;
    }

    public AxdrNull getNom() {
        return nom;
    }

    public AxdrNull getAllmaddr() {
        return allmaddr;
    }

    public SubSeqOfUnsigned8 getGroupmtype() {
        return groupmtype;
    }

    public SubSeqOfTsa getGroupmaddr() {
        return groupmaddr;
    }

    public SubSeqOfUnsigned16 getGroupsetindex() {
        return groupsetindex;
    }

    public SubSeqOfRegion getRegiontype() {
        return regiontype;
    }

    public SubSeqOfRegion getRegionaddr() {
        return regionaddr;
    }

    public SubSeqOfRegion getRegionsetindex() {
        return regionsetindex;
    }

    public void set_dataCode(byte[] dataCode) {
        this.dataCode = dataCode;
    }

    public int decode(ReverseByteArrayInputStream input) throws Exception {
        int codeLength = 0;
        AxdrEnum choosen = new AxdrEnum();
        choosen.setConst();
        codeLength += choosen.decode(input);
        resetChoices();
        choice = Choice.getEnumByValue((int)choosen.getValue());
        if (choice == Choice.NOM) {
            nom = new AxdrNull();
            codeLength += nom.decode(input);
            return codeLength;
        }
        if (choice == Choice.ALLMADDR) {
            allmaddr = new AxdrNull();
            codeLength += allmaddr.decode(input);
            return codeLength;
        }
        if (choice == Choice.GROUPMTYPE) {
            groupmtype = new SubSeqOfUnsigned8();
            codeLength += groupmtype.decode(input);
            return codeLength;
        }
        if (choice == Choice.GROUPMADDR) {
            groupmaddr = new SubSeqOfTsa();
            codeLength += groupmaddr.decode(input);
            return codeLength;
        }
        if (choice == Choice.GROUPSETINDEX) {
            groupsetindex = new SubSeqOfUnsigned16();
            codeLength += groupsetindex.decode(input);
            return codeLength;
        }
        if (choice == Choice.REGIONTYPE) {
            regiontype = new SubSeqOfRegion();
            codeLength += regiontype.decode(input);
            return codeLength;
        }
        if (choice == Choice.REGIONADDR) {
            regionaddr = new SubSeqOfRegion();
            codeLength += regionaddr.decode(input);
            return codeLength;
        }
        if (choice == Choice.REGIONSETINDEX) {
            regionsetindex = new SubSeqOfRegion();
            codeLength += regionsetindex.decode(input);
            return codeLength;
        }
        throw new Exception("Error decoding AxdrChoice: Identifier matched to no item.");
    }

    public int encode(ReverseByteArrayOutputStream output) throws Exception {
        if (dataCode != null) {
            for (int i = dataCode.length - 1; i >= 0; i--) {
                output.write(dataCode[i]);
            }
            return dataCode.length;
        }
        if (choice == Choice._ERR_NONE_SELECTED) {
            throw new Exception("Error encoding AxdrChoice: No item in choice was selected.");
        }
        int codeLength = 0;
        if (choice == Choice.REGIONSETINDEX) {
            codeLength += regionsetindex.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(7);
            codeLength += c.encode(output);
            return codeLength;
        }
        if (choice == Choice.REGIONADDR) {
            codeLength += regionaddr.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(6);
            codeLength += c.encode(output);
            return codeLength;
        }
        if (choice == Choice.REGIONTYPE) {
            codeLength += regiontype.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(5);
            codeLength += c.encode(output);
            return codeLength;
        }
        if (choice == Choice.GROUPSETINDEX) {
            codeLength += groupsetindex.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(4);
            codeLength += c.encode(output);
            return codeLength;
        }
        if (choice == Choice.GROUPMADDR) {
            codeLength += groupmaddr.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(3);
            codeLength += c.encode(output);
            return codeLength;
        }
        if (choice == Choice.GROUPMTYPE) {
            codeLength += groupmtype.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(2);
            codeLength += c.encode(output);
            return codeLength;
        }
        if (choice == Choice.ALLMADDR) {
            codeLength += allmaddr.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(1);
            codeLength += c.encode(output);
            return codeLength;
        }
        if (choice == Choice.NOM) {
            codeLength += nom.encode(output);
            AxdrEnum c = new AxdrEnum();
            c.setMinMaxVal(0);
            codeLength += c.encode(output);
            return codeLength;
        }
        throw new Exception("Error encoding AxdrChoice: No item in choice was encoded.");
    }

    public void resetChoices() {
        choice = Choice._ERR_NONE_SELECTED;
        nom = null;
        allmaddr = null;
        groupmtype = null;
        groupmaddr = null;
        groupsetindex = null;
        regiontype = null;
        regionaddr = null;
        regionsetindex = null;
    }

    public void encodeAndSave(int encodingSizeGuess) throws Exception {
        ReverseByteArrayOutputStream revOStream = new ReverseByteArrayOutputStream();
        revOStream.setBufSize(encodingSizeGuess);
        encode(revOStream);
        dataCode = revOStream.getArray();
    }

    public Choice getChoiceIndex() {
        return choice;
    }

    public void setNom(AxdrNull nom) {
        resetChoices();
        choice = Choice.NOM;
        this.nom = nom;
    }

    public void setAllmaddr(AxdrNull allmaddr) {
        resetChoices();
        choice = Choice.ALLMADDR;
        this.allmaddr = allmaddr;
    }

    public void setGroupmtype(SubSeqOfUnsigned8 groupmtype) {
        resetChoices();
        choice = Choice.GROUPMTYPE;
        this.groupmtype = groupmtype;
    }

    public void setGroupmaddr(SubSeqOfTsa groupmaddr) {
        resetChoices();
        choice = Choice.GROUPMADDR;
        this.groupmaddr = groupmaddr;
    }

    public void setGroupsetindex(SubSeqOfUnsigned16 groupsetindex) {
        resetChoices();
        choice = Choice.GROUPSETINDEX;
        this.groupsetindex = groupsetindex;
    }

    public void setRegiontype(SubSeqOfRegion regiontype) {
        resetChoices();
        choice = Choice.REGIONTYPE;
        this.regiontype = regiontype;
    }

    public void setRegionaddr(SubSeqOfRegion regionaddr) {
        resetChoices();
        choice = Choice.REGIONADDR;
        this.regionaddr = regionaddr;
    }

    public void setRegionsetindex(SubSeqOfRegion regionsetindex) {
        resetChoices();
        choice = Choice.REGIONSETINDEX;
        this.regionsetindex = regionsetindex;
    }

    @Override
    public String toString() {
        if (choice == Choice.NOM) {
            if (nom != null) {
                return "choice: {nom: " + nom + "}";
            } else {
                return "choice is nom but nom is null";
            }
        } else if (choice == Choice.ALLMADDR) {
            if (allmaddr != null) {
                return "choice: {allmaddr: " + allmaddr + "}";
            } else {
                return "choice is allmaddr but allmaddr is null";
            }
        } else if (choice == Choice.GROUPMTYPE) {
            if (groupmtype != null) {
                return "choice: {groupmtype: " + groupmtype + "}";
            } else {
                return "choice is groupmtype but groupmtype is null";
            }
        } else if (choice == Choice.GROUPMADDR) {
            if (groupmaddr != null) {
                return "choice: {groupmaddr: " + groupmaddr + "}";
            } else {
                return "choice is groupmaddr but groupmaddr is null";
            }
        } else if (choice == Choice.GROUPSETINDEX) {
            if (groupsetindex != null) {
                return "choice: {groupsetindex: " + groupsetindex + "}";
            } else {
                return "choice is groupsetindex but groupsetindex is null";
            }
        } else if (choice == Choice.REGIONTYPE) {
            if (regiontype != null) {
                return "choice: {regiontype: " + regiontype + "}";
            } else {
                return "choice is regiontype but regiontype is null";
            }
        } else if (choice == Choice.REGIONADDR) {
            if (regionaddr != null) {
                return "choice: {regionaddr: " + regionaddr + "}";
            } else {
                return "choice is regionaddr but regionaddr is null";
            }
        } else if (choice == Choice.REGIONSETINDEX) {
            if (regionsetindex != null) {
                return "choice: {regionsetindex: " + regionsetindex + "}";
            } else {
                return "choice is regionsetindex but regionsetindex is null";
            }
        } else {
            return "unknown";
        }
    }

    public enum Choice {
        _ERR_NONE_SELECTED(-1),
        NOM(0),
        ALLMADDR(1),
        GROUPMTYPE(2),
        GROUPMADDR(3),
        GROUPSETINDEX(4),
        REGIONTYPE(5),
        REGIONADDR(6),
        REGIONSETINDEX(7);

        private final int value;

        Choice(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public static Choice getEnumByValue(int value) {
            for (Choice item : Choice.values()) {
                if (value == item.getValue()) {
                    return item;
                }
            }
            return null;
        }
    }
}



